package com.android.tetris;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.tetris.utils.Utils;
import com.android.tetris.utils.Values;

public class Game extends Activity implements OnClickListener {
	private GameView gameBoard;
	private int d; // The side of a box
	private Tile[][] box;
	private int x, y;
	private Display display;
	private CountDownTimer timer, timerLevel1, timerLevel2, timerLevel3,
			timerLevel4, timerLevel5;
	private Shape currentShape;
	private Shape nextShape;
	private boolean pieceOnGame;
	private Button btnMoveRight, btnMoveLeft, btnMoveDown, btnRotateRight,
			btnRotateLeft, btnPause;
	private ImageView nextShapeImg;
	private TextView txtTimeRemain;
	// Score and combo
	private TextView txtScore;
	private TextView txtLevel;
	private ImageView imageCombo;
	private int score = 0;
	private int combo = 1;
	// private Vibrator vibrator;
	// The pause indicator
	private boolean game;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.game);

		Utils.PlayTimeFinished = Values.TIME_FINISHING;
		// Khoi tao cac thanh phan cua View
		initView();
	}

	/**
	 * Khoi tao cac thanh phan cua View
	 */
	private void initView() {
		// Set tham chieu den cac button trong Game view
		btnMoveRight = (Button) findViewById(R.id.btnMoveR);
		btnMoveLeft = (Button) findViewById(R.id.btnMoveL);
		btnMoveDown = (Button) findViewById(R.id.btnMoveD);
		btnRotateRight = (Button) findViewById(R.id.btnRotateR);
		btnRotateLeft = (Button) findViewById(R.id.btnRotateL);
		btnPause = (Button) findViewById(R.id.btnPause);

		// Set Action cho cac button
		btnMoveRight.setOnClickListener(this);
		btnMoveLeft.setOnClickListener(this);
		btnMoveDown.setOnClickListener(this);
		btnRotateRight.setOnClickListener(this);
		btnRotateLeft.setOnClickListener(this);
		btnPause.setOnClickListener(this);

		// Lay kich thuoc cua GameView
		display = getWindowManager().getDefaultDisplay();
		// Width = 70% kich thuoc toan man hinh
		int width = (int) (display.getWidth() * 0.7);
		// Height = 90% kich thuoc toan man hinh
		int height = (int) (display.getHeight() * 0.9);
		gameBoard = (GameView) findViewById(R.id.GameView);
		// Kich thuoc cua 1 thanh phan wall
		d = (int) (width * 0.85 / Values.NUM_COL);

		txtTimeRemain = (TextView) findViewById(R.id.txtTimeRemain);
		// Set tham chieu den score va combo
		txtScore = (TextView) findViewById(R.id.txtScore);
		txtLevel = (TextView) findViewById(R.id.txtLevel);
		imageCombo = (ImageView) findViewById(R.id.imgCombo);

		// Tao box va cac duong bien
		box = new Tile[Values.NUM_ROW][Values.NUM_COL];
		x = (int) (width * 0.05);
		y = (int) (height * 0.05);

		// Ve wall
		gameBoard.createWall(x, y, d);

		for (int i = 0; i < Values.NUM_ROW; i++) {
			x = (int) (width * 0.05);
			for (int j = 0; j < Values.NUM_COL; j++) {
				box[i][j] = new Tile(x + d * j, y + d * i, d);
				gameBoard.initialize(i, j, x, y, d);
				x = x + d;
			}
			y = y + d;
		}

		// Khoi tao hieu ung rung
		// vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

		// Khoi tao cac vien gach (Shapes)
		currentShape = new Shape();
		nextShape = new Shape();
		nextShapeImg = (ImageView) findViewById(R.id.imgNext);

		// Start Game
		game = true;
		timer = new CountDownTimer(Utils.PlayTimeFinished, 1000) {
			public void onTick(long millisUntilFinished) {
				updateView();
			}

			public void onFinish() {
				Utils.PlayingSecond = 0;
				Utils.CurrentLevel = 1;
				gameAction();
				start();
			}
		}.start();

		txtScore.setText("0");
		txtLevel.setText("1");
		currentShape.start();

		// Khoi tao vien gach tiep theo
		switch (nextShape.getType()) {
		case Values.SHAPE_0:
			nextShapeImg.setImageResource(R.drawable.piece0);
			break;
		case Values.SHAPE_1:
			nextShapeImg.setImageResource(R.drawable.piece1);
			break;
		case Values.SHAPE_2:
			nextShapeImg.setImageResource(R.drawable.piece2);
			break;
		case Values.SHAPE_3:
			nextShapeImg.setImageResource(R.drawable.piece3);
			break;
		case Values.SHAPE_4:
			nextShapeImg.setImageResource(R.drawable.piece4);
			break;
		case Values.SHAPE_5:
			nextShapeImg.setImageResource(R.drawable.piece5);
			break;
		case Values.SHAPE_6:
			nextShapeImg.setImageResource(R.drawable.piece6);
			break;
		}
	}

	/**
	 * Shape duoc cau thanh tu cac Tile, trong so cac Tile se chi co 1 so Tile
	 * duoc set = true, nhung Tile con lai se coi nhu free, va khong duoc ve
	 * tren GameView
	 */
	public void unDraw() {
		for (int i = 0; i < Values.NUM_ROW; i++)
			for (int j = 0; j < Values.NUM_COL; j++) {
				if (currentShape.getBox()[i][j]) {
					box[i][j].setColor(0);
					gameBoard.setColor(i, j, (byte) 0);
				}
			}
	}

	/**
	 * Shape duoc cau thanh tu cac Tile, trong so cac Tile se chi co 1 so Tile
	 * duoc set = true, nhung Tile nay se duoc ve tren GameView
	 */
	public void reDraw() {
		for (int i = 0; i < Values.NUM_ROW; i++)
			for (int j = 0; j < Values.NUM_COL; j++) {
				if (currentShape.getBox()[i][j]) {
					box[i][j].setColor(currentShape.getColor());
					gameBoard.setColor(i, j, currentShape.getColor());
				}
			}
	}

	/**
	 * Xoa dong khi nguoi dung ghi diem
	 * 
	 * @param row
	 */
	public void removeRow(int row) {
		score = score + Values.SCORE_PER_ROW * combo;
		txtScore.setText(Integer.toString(score));

		// Cap nhat combo
		combo = combo * 2;

		if (combo == 32) {
			combo = 16;
		}

		switch (combo) {
		case 2:
			imageCombo.setImageResource(R.drawable.x2);
			break;
		case 4:
			imageCombo.setImageResource(R.drawable.x4);
			break;
		case 8:
			imageCombo.setImageResource(R.drawable.x8);
			break;
		case 16:
			imageCombo.setImageResource(R.drawable.x16);
			break;
		}

		// Ve lai cac dong khi nguoi dung ghi diem, dong thu i se duoc ve lai
		// bang dong thu i - 1
		for (int i = row; i > 1; i--) {
			for (int j = 0; j < Values.NUM_COL; j++) {
				box[i][j].setColor(box[i - 1][j].getColor());
				gameBoard.setColor(i, j, (byte) box[i - 1][j].getColor());
			}
		}
	}

	/**
	 * Xac dinh dong se bi xoa di (dong bi xoa di la dong khong co Tile free)
	 * 
	 * @return
	 */
	public boolean lookForRows() {
		boolean somethingRemoved = false;
		boolean full = true;
		for (int i = 1; i < Values.NUM_ROW; i++) {
			full = true;
			for (int j = 0; j < Values.NUM_COL; j++) {
				if (box[i][j].getColor() == Values.COLOR_NONE) {
					full = false;
				}
			}
			if (full == true) {
				somethingRemoved = true;
				removeRow(i);
			}
		}
		return somethingRemoved;
	}

	/**
	 * Kiem tra nguoi dung da thua hay chua
	 */
	private void checkGameLoose() {
		int hScore1, hScore2, hScore3, hScore4, hScore5, aux;
		String hScore1Date, hScore2Date, hScore3Date, hScore4Date, hScore5Date, auxDate;
		boolean loose = false;

		// Nguoi choi duoc xem la thua neu tat ca cac cot cua dong (ke dong tren
		// cung) deu co Tile (not free)
		for (int j = 0; j < Values.NUM_COL; j++) {
			if (box[1][j].getColor() != Values.COLOR_NONE) {
				loose = true;
			}
		}

		if (!loose) {
			return;
		}

		// Game lose, cap nhat lai trang thai cua Game
		game = false;
		Utils.PlayingSecond = 0;
		Utils.CurrentLevel = 1;
		// Cap nhat hieu ung rung
		// vibrator.vibrate(1000);

		// Lay thong ke diem hien thoi
		SharedPreferences highScores = getSharedPreferences("highScores", 0);

		hScore1 = highScores.getInt("hScore1", 0);
		hScore2 = highScores.getInt("hScore2", 0);
		hScore3 = highScores.getInt("hScore3", 0);
		hScore4 = highScores.getInt("hScore4", 0);
		hScore5 = highScores.getInt("hScore5", 0);

		hScore1Date = highScores.getString("hScore1Date", "0");
		hScore2Date = highScores.getString("hScore2Date", "0");
		hScore3Date = highScores.getString("hScore3Date", "0");
		hScore4Date = highScores.getString("hScore4Date", "0");
		hScore5Date = highScores.getString("hScore5Date", "0");

		// Lay ngay hien thoi
		Calendar currentDate = Calendar.getInstance();
		Date dateNow = currentDate.getTime();

		if (score > hScore5) {
			Format formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
			hScore5 = score;
			hScore5Date = formatter.format(dateNow);
		}
		if (hScore5 > hScore4) {
			aux = hScore4;
			auxDate = hScore4Date;
			hScore4 = hScore5;
			hScore4Date = hScore5Date;
			hScore5 = aux;
			hScore5Date = auxDate;
		}
		if (hScore4 > hScore3) {
			aux = hScore3;
			auxDate = hScore3Date;
			hScore3 = hScore4;
			hScore3Date = hScore4Date;
			hScore4 = aux;
			hScore4Date = auxDate;
		}
		if (hScore3 > hScore2) {
			aux = hScore2;
			auxDate = hScore2Date;
			hScore2 = hScore3;
			hScore2Date = hScore3Date;
			hScore3 = aux;
			hScore3Date = auxDate;
		}
		if (hScore2 > hScore1) {
			aux = hScore1;
			auxDate = hScore1Date;
			hScore1 = hScore2;
			hScore1Date = hScore2Date;
			hScore2 = aux;
			hScore2Date = auxDate;
		}

		// Cap nhat lai bang thong ke diem cua 3 nguoi choi co diem so cao nhat
		SharedPreferences.Editor editor = highScores.edit();

		editor.putInt("hScore1", hScore1);
		editor.putInt("hScore2", hScore2);
		editor.putInt("hScore3", hScore3);
		editor.putInt("hScore4", hScore4);
		editor.putInt("hScore5", hScore5);

		editor.putString("hScore1Date", hScore1Date);
		editor.putString("hScore2Date", hScore1Date);
		editor.putString("hScore3Date", hScore1Date);
		editor.putString("hScore4Date", hScore1Date);
		editor.putString("hScore5Date", hScore1Date);

		editor.commit();

		// Hien thi dialog ve thong ke diem so
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.gameover);
		builder.setMessage("Điểm số: " + txtScore.getText().toString())
				.setCancelable(false)
				.setNegativeButton(R.string.exit,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
								finish();
							}
						});
		AlertDialog endGameAlert = builder.create();
		endGameAlert.show();
	}

	private void updateView() {
		if (game) {
			Utils.PlayingSecond++;
			Utils.PlayTimeFinished = (Utils.PlayTimeFinished / 1000 - 1) * 1000;
			long sec = Utils.PlayTimeFinished / 1000;
			txtTimeRemain.setText(String.valueOf((sec / (60 * 60))%24) + ":"
					+ String.valueOf((sec / (60)) % 60) + ":"
					+ String.valueOf(sec % 60));

			if (Utils.PlayingSecond >= Values.TIME_LEVEL4TO5) {
				Utils.CurrentLevel = 5;
			} else if (Utils.PlayingSecond >= Values.TIME_LEVEL3TO4) {
				Utils.CurrentLevel = 4;
			} else if (Utils.PlayingSecond >= Values.TIME_LEVEL2TO3) {
				Utils.CurrentLevel = 3;
			} else if (Utils.PlayingSecond >= Values.TIME_LEVEL1TO2) {
				Utils.CurrentLevel = 2;
			} else {
				Utils.CurrentLevel = 1;
			}

			txtLevel.setText(String.valueOf(Utils.CurrentLevel));

			// Level 1
			if (Utils.CurrentLevel == 1) {

				if (timerLevel2 != null) {
					timerLevel2.cancel();
				}
				if (timerLevel3 != null) {
					timerLevel3.cancel();
				}
				if (timerLevel4 != null) {
					timerLevel4.cancel();
				}
				if (timerLevel5 != null) {
					timerLevel5.cancel();
				}

				if (timerLevel1 == null) {
					timerLevel1 = new CountDownTimer(Utils.PlayTimeFinished,
							Values.TIME_RATE_LEVEL1) {
						public void onTick(long millisUntilFinished) {
							gameAction();
						}

						@Override
						public void onFinish() {
							// TODO Auto-generated method stub
						}
					}.start();
				}
			} else if (Utils.CurrentLevel == 2) {
				// Level 2

				if (timerLevel1 != null) {
					timerLevel1.cancel();
				}
				if (timerLevel3 != null) {
					timerLevel3.cancel();
				}
				if (timerLevel4 != null) {
					timerLevel4.cancel();
				}
				if (timerLevel5 != null) {
					timerLevel5.cancel();
				}

				if (timerLevel2 == null) {
					timerLevel2 = new CountDownTimer(Utils.PlayTimeFinished,
							Values.TIME_RATE_LEVEL2) {
						public void onTick(long millisUntilFinished) {
							gameAction();
						}

						@Override
						public void onFinish() {
							// TODO Auto-generated method stub
						}
					}.start();
				}
			} else if (Utils.CurrentLevel == 3) {
				// Level 3

				if (timerLevel1 != null) {
					timerLevel1.cancel();
				}
				if (timerLevel2 != null) {
					timerLevel2.cancel();
				}
				if (timerLevel4 != null) {
					timerLevel4.cancel();
				}
				if (timerLevel5 != null) {
					timerLevel5.cancel();
				}

				if (timerLevel3 == null) {
					timerLevel3 = new CountDownTimer(Utils.PlayTimeFinished,
							Values.TIME_RATE_LEVEL3) {
						public void onTick(long millisUntilFinished) {
							gameAction();
						}

						@Override
						public void onFinish() {
							// TODO Auto-generated method stub
						}
					}.start();
				}
			} else if (Utils.CurrentLevel == 4) {
				// Level 4

				if (timerLevel1 != null) {
					timerLevel1.cancel();
				}
				if (timerLevel2 != null) {
					timerLevel2.cancel();
				}
				if (timerLevel3 != null) {
					timerLevel3.cancel();
				}
				if (timerLevel5 != null) {
					timerLevel5.cancel();
				}

				if (timerLevel4 == null) {
					timerLevel4 = new CountDownTimer(Utils.PlayTimeFinished,
							Values.TIME_RATE_LEVEL4) {
						public void onTick(long millisUntilFinished) {
							gameAction();
						}

						@Override
						public void onFinish() {
							// TODO Auto-generated method stub
						}
					}.start();
				}
			} else if (Utils.CurrentLevel == 5) {
				// Level 5

				if (timerLevel1 != null) {
					timerLevel1.cancel();
				}
				if (timerLevel2 != null) {
					timerLevel2.cancel();
				}
				if (timerLevel3 != null) {
					timerLevel3.cancel();
				}
				if (timerLevel4 != null) {
					timerLevel4.cancel();
				}

				if (timerLevel5 == null) {
					timerLevel5 = new CountDownTimer(Utils.PlayTimeFinished,
							Values.TIME_RATE_LEVEL5) {
						public void onTick(long millisUntilFinished) {
							gameAction();
						}

						@Override
						public void onFinish() {
							// TODO Auto-generated method stub
						}
					}.start();
				}
			}
		}
	}

	/**
	 * Cap nhat lai GameView
	 */
	private void gameAction() {
		if (game) {
			unDraw();
			// Not down
			if (!currentShape.moveDown()) {
				for (int i = 0; i < Values.NUM_ROW; i++) {
					for (int j = 0; j < Values.NUM_COL; j++) {
						if (currentShape.getBox()[i][j]) {
							box[i][j].setColor(currentShape.getColor());
							gameBoard.setColor(i, j, currentShape.getColor());
						}
					}
				}

				if (!lookForRows()) {
					combo = 1; // Khong co dong duoc xoa, set combo = 1
					imageCombo.setImageResource(R.drawable.alpha);
				}

				// Kiem tra tro choi ket thuc hay chua
				checkGameLoose();

				// Cap nhat Shape hien thoi
				currentShape = nextShape;
				currentShape.start();
				nextShape = new Shape();

				// Cap nhat Shape ke tiep
				switch (nextShape.getType()) {
				case Values.SHAPE_0:
					nextShapeImg.setImageResource(R.drawable.piece0);
					break;
				case Values.SHAPE_1:
					nextShapeImg.setImageResource(R.drawable.piece1);
					break;
				case Values.SHAPE_2:
					nextShapeImg.setImageResource(R.drawable.piece2);
					break;
				case Values.SHAPE_3:
					nextShapeImg.setImageResource(R.drawable.piece3);
					break;
				case Values.SHAPE_4:
					nextShapeImg.setImageResource(R.drawable.piece4);
					break;
				case Values.SHAPE_5:
					nextShapeImg.setImageResource(R.drawable.piece5);
					break;
				case Values.SHAPE_6:
					nextShapeImg.setImageResource(R.drawable.piece6);
					break;
				}
			}
			currentShape.readBoard(box);
			reDraw();
		}
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.btnMoveR:
			unDraw();
			currentShape.moveRight();
			// vibrator.vibrate(30);
			reDraw();
			break;
		case R.id.btnMoveL:
			unDraw();
			currentShape.moveLeft();
			// vibrator.vibrate(30);
			reDraw();
			break;
		case R.id.btnMoveD:
			unDraw();
			currentShape.moveDown();
			// vibrator.vibrate(30);
			reDraw();
			break;
		case R.id.btnRotateR:
			unDraw();
			currentShape.rotateRight();
			// vibrator.vibrate(30);
			reDraw();
			break;
		case R.id.btnRotateL:
			unDraw();
			currentShape.rotateLeft();
			// vibrator.vibrate(30);
			reDraw();
			break;
		case R.id.btnPause:
			if (game == true) {
				game = false;
				btnPause.setText(R.string.resume);
			} else {
				game = true;
				btnPause.setText(R.string.pause);
			}
			// vibrator.vibrate(30);
			break;
		}

	}
}
